package tools

import (
	"embed"
	"fmt"
	"iris-wms/common/tools/consts"
	"strings"

	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
	"gopkg.in/yaml.v3"
)

var GConfig *Global

type Global struct {
	Boot Boot
	App  App
}

// var G_IFacePolicys []*out.IFacePolicy

// 配置文件对应的结构体
type Boot struct {
	Servername         string `yaml:"Servername"`
	AppOwner           string `yaml:"AppOwner"`
	Version            string `yaml:"Version"`
	Profile            string `yaml:"Profile"`
	Port               int    `yaml:"Port"`
	BboltFilename      string `yaml:"BboltFilename"`
	SystemBucket       string `yaml:"SystembBucket"`
	iris.Configuration `yaml:"Configuration"`
}
type (
	App struct {
		JWT       JWT       `yaml:"JWT"`
		Casbin    Casbin    `yaml:"Casbin"`
		Websocket Websocket `yaml:"Websocket"`
		Gorm      Gorm      `yaml:"Gorm"`
		File      File      `yaml:"File"`
		Redis     struct {
			Addr     string `yaml:"Addr"`
			Password string `yaml:"Password"`
			DB       int    `yaml:"Db"`
			PoolSize int    `yaml:"PoolSize"`
		} `yaml:"Redis"`
		Mysql struct {
			SelectList []string `yaml:"SelectList"`
			Db1        DBInfo   `yaml:"Db1"`
			Db2        DBInfo   `yaml:"Db2"`
		} `yaml:"Mysql"`
		IgnoreUrls       []string `yaml:"IgnoreUrls"`
		LogBatchSize     int      `yaml:"LogBatchSize"`
		LogCommitTimeout int      `yaml:"LogCommitTimeout"`
		RootUsername     string   `yaml:"RootUsername"`
		RootPassword     string   `yaml:"RootPassword"`
	}
	JWT struct {
		JWTTimeout int    `yaml:"JWTTimeout"`
		JWTSecret  string `yaml:"JWTSecret"`
	}
	Casbin struct {
		Debug  bool   `yaml:"Debug"`
		Table  string `yaml:"Table"`
		Tenant string `yaml:"Tenant"`
	}
	Websocket struct {
		Pool string `yaml:"Pool"`
	}
	Gorm struct {
		Debug            bool   `yaml:"Debug"`
		OutPath          string `yaml:"OutPath"`
		GenerateDao      bool   `yaml:"GenerateDao"`
		GenerateAllTable bool   `yaml:"GenerateAllTable"`
		AutoMigrate      bool   `yaml:"AutoMigrate"`
		InitData         bool   `yaml:"InitData"`
		InitPolicy       bool   `yaml:"InitPolicy"`
	}
	File struct {
		Image    string `yaml:"Image"`
		Template string `yaml:"Template"`
	}
)

// mysql 通用配置字段
type DBInfo struct {
	Dialect      string `yaml:"Dialect"`
	User         string `yaml:"User"`
	Password     string `yaml:"Password"`
	Host         string `yaml:"Host"`
	Port         int    `yaml:"Port"`
	Database     string `yaml:"Database"`
	Charset      string `yaml:"Charset"`
	ShowSql      bool   `yaml:"ShowSql"`
	LogLevel     string `yaml:"LogLevel"`
	MaxOpenConns int    `yaml:"MaxOpenConns"`
	MaxIdleConns int    `yaml:"MaxIdleConns"`
	//ParseTime       bool   `yaml:"ParseTime"`
	//MaxIdleConns    int    `yaml:"MaxIdleConns"`
	//MaxOpenConns    int    `yaml:"MaxOpenConns"`
	//ConnMaxLifetime int64  `yaml:"ConnMaxLifetime: 10"`
	//Sslmode         string `yaml:"Sslmode"`
}

func (conf Global) DBConnUrl(info DBInfo) string {
	return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True",
		info.User,
		info.Password,
		info.Host,
		info.Port,
		info.Database,
		info.Charset,
	)
}

// 初始化全局配置
func InitGlobalConfig(conf embed.FS) ([]byte, error) {
	var (
		prefix = "conf/app-%s.yaml"
		data   []byte
		err    error
	)
	GConfig = &Global{Boot: Boot{}, App: App{}}
	// boot
	data, err = conf.ReadFile("conf/boot.yaml")
	if err != nil {
		goto ERR
	}
	if err := yaml.Unmarshal(data, &GConfig.Boot); err != nil {
		goto ERR
	}
	// 判断 Profile
	if GConfig.Boot.Profile == "" ||
		strings.EqualFold(GConfig.Boot.Profile, consts.PROFILE_DEV) {
		GConfig.Boot.Profile = fmt.Sprintf(prefix, consts.PROFILE_DEV)
	} else if strings.EqualFold(GConfig.Boot.Profile, consts.PROFILE_TEST) {
		GConfig.Boot.Profile = fmt.Sprintf(prefix, consts.PROFILE_TEST)
	} else if strings.EqualFold(GConfig.Boot.Profile, consts.PROFILE_PROD) {
		GConfig.Boot.Profile = fmt.Sprintf(prefix, consts.PROFILE_PROD)
	}
	// app
	data, err = conf.ReadFile(GConfig.Boot.Profile)
	if err != nil {
		goto ERR
	}
	if err := yaml.Unmarshal(data, &GConfig.App); err != nil {
		goto ERR
	}
	return nil, err
ERR:
	golog.Fatalf("Global-config init err:%s", err.Error())
	return nil, err
}
